# 1== add aditional validation from ActiveMerchant and from schof_spree

class BillingCreditCard < ActiveRecord::Base
  belongs_to :billing_profile
  
  # create new account
    attr_accessor :card_verification,
                  :zipcode,
                  :customer_profile_id
                  # for additional table address (presenter)
                  # probably need to add to this table ??? from gateway only 
                                        # where we have to store CreditCard outside(Autorize.net or PayPal)
    attr_reader :customer_profile_id
    
    before_create :credit_card_create
    # after_create  :activate! if 
    before_update :credit_card_update
    before_destroy :credit_card_delete
    
    before_validation :prepare, :on => [:create, :update]
    
    include ActiveMerchant::Billing::CreditCardMethods
    
    def prepare
      # credit_card
      # if billing_profile?
      #         billing_profile = BillingProfile.find(billing_profile_id)
      #       end
      
      # self.billing_profile = 
    end
    
    def validate
      validate_essential_attributes
      validate_credit_card
      validate_base
      valudate_additional_attributes
    end
    
    def validate_essential_attributes #:nodoc:
      errors.add :first_name, "cannot be empty" if first_name.blank?
      errors.add :last_name, "cannot be empty" if last_name.blank?
      errors.add :expires_at_month, "is not a valid month" unless valid_month?(expires_at_month)
      # check expiration date!!!!!
      errors.add :expires_at_year, "expired" if expired?
      errors.add :expires_at_year, "is not a valid year" unless valid_expiry_year?(expires_at_year)
    end
    
    def validate_credit_card
      # errors.add :card_number, "cannot be empty" if card_number.blank?
      errors.add :card_number, "is not a valid credit card number" unless BillingAmCreditCard.valid_number?(card_number)
      errors.add :card_verification, "cannot be empty" if card_verification.blank?
      # unless errors.on(:number) || errors.on(:cc_type)
      #   errors.add :cc_type, "is not the correct card type" unless Creditcard.matching_type?(number, cc_type)
      # end
    end
    
    def validate_base
      # unless @credit_card.valid?
      #    @credit_card.errors.full_messages.each do |message|
      #      errors.add_to_base message
      #    end
      #  end
    end
    
    def valudate_additional_attributes
      # validate address add later
      #validate existing zipcode!!!!!
      errors.add :zipcode, "cannot be empty" if zipcode.blank?
    end
    
    def expiry_date
      return Date.new(expires_at_year, expires_at_month, 1) rescue Date.today
    end

    def expired?
      return expiry_date < Date.today
    end
    
    
    # before_delete :credit_card_delete
    
    # after _create   validate uniquness of primary account
    
    # validates_uniqueness_of :account_primary, :scope => [:application_account_id], :message => "must be unique"
    
    # 
    #  # # before_validation :credit_card
    #  # validate :credit_card_update, :on => :update, :if => :update_action?
    # 
    #  after_create :credit_card_store
    #  # validate :credit_card_store
    #  # before_update :credit_card_update
    # 
    #  before_destroy :credit_card_delete


    # Validations -----------------------------------------------------
    #validates_presence_of   #:billing_profile_id,  # only for Authorize.net/PayPal store CredCard outside
                            #:customer_profile_id, # only for Authorize.net/PayPal store CredCard outside
    # validates_presence_of   :card_number, :card_verification, 
    #                         :first_name, :last_name, 
    #                         :expires_at_month, :expires_at_year, 
    #                         :card_type, # - not mandatory parametr for ActiveMerchant
    #                         :zipcode, 
    #                         
    #                         :on => :create
     # ?????                       
    # validates_numericality_of :card_number, :card_verification, 
    #                             :expires_at_year, :expires_at_month

    # validates_uniqueness_of 
    # -----------------------------------------------------------------

    #----- Act as FINITE STATE MACHINE -------------
      acts_as_state_machine :initial => :inactive, :column => :status

      state :inactive, :column => :status
      state :active, :column => :status
      state :canceled, :column => :status
      state :error, :column => :status

      event :activate do
         transitions :from => :inactive, :to => :active
      end

      event :cancel do
        transitions :from => :active, :to => :canceled
      end
      
      event :error do
        transitions :from => :inactive, :to => :error
        transitions :from => :active, :to => :error
      end
      
      # reference of statuses for this model
      def self.statuses
        [RefActionStatus::ACTIVE, RefActionStatus::INACTIVE]
      end
    #-----------------------------------------------

    def credit_card_create
      credit_card      
      # 1== validate_credit_card
      begin
        @credit_card.store_profile_credit_card
        self.card_number = @credit_card.display_number
        self.customer_profile_id ||= @credit_card.out_options[:customer_profile_id]
        # self.billing_profile.customer_profile_id ||= @credit_card.out_options[:customer_profile_id]
        self.billing_profile.update_attributes({:customer_profile_id => @credit_card.out_options[:customer_profile_id]}) if self.billing_profile.customer_profile_id.nil?
        # user_profile!!!!
        self.customer_payment_id = @credit_card.out_options[:customer_payment_profile_id]
        self.status = RefActionStatus::ACTIVE
        # self.activate!
      rescue ZepFrog::PaymentError => e
        # self.msg err message
        errors.add_to_base @credit_card.out_options[:msg]
        errors.add_to_base e.inspect
        raise ZepFrog::CustomError, @credit_card.out_options[:msg]
      end
    end
    
    
    def credit_card_update
      # errors.add_to_base "UPDATE NOT included to this version"
      # raise ZepFrog::CustomError, (self.class.to_s + "." + "credit_card_update" + ":" + (errors.full_messages.to_s || "Do not allow update now!!!"))
      credit_card
      # 1== validate_credit_card
      begin
        self.card_number = @credit_card.display_number
        @credit_card.update_customer_payment_profile
        self.customer_profile_id ||= @credit_card.out_options[:customer_profile_id]
        # self.billing_profile.update_attributes({:customer_profile_id => @credit_card.out_options[:customer_profile_id]}) if self.billing_profile.customer_profile_id.nil?
        
        # user_profile!!!!
        self.customer_payment_id = @credit_card.out_options[:customer_payment_profile_id]
      rescue ZepFrog::PaymentError => e
        # self.msg err message logging
        errors.add_to_base @credit_card.out_options[:msg]
        errors.add_to_base e.inspect
        raise ZepFrog::CustomError, @credit_card.out_options[:msg]
      end
    end

    def credit_card_delete
      # Don't allow to delete just change status
      
      begin
        BillingAmCreditCard.delete_customer_payment_profile({:customer_profile_id => self.billing_profile.customer_profile_id, 
                          :customer_payment_profile_id => customer_payment_id})
        self.cancel!
      rescue ZepFrog::PaymentError => e
        # self.msg err message logging
        # errors.add_to_base @credit_card.out_options[:msg]
        errors.add_to_base e.inspect
        raise ZepFrog::CustomError, e.to_s
      end
      

    end
    
    
    # private
    
    # validate all params mandatory
    def credit_card
      @credit_card = BillingAmCreditCard.new({:main => {
           :number     => card_number,
           :month      => expires_at_month,
           :year       => expires_at_year,
           :first_name => first_name,
           :last_name  => last_name,
           :verification_value  => card_verification,
           :type       => card_type},
           :add_options => {:zipcode => zipcode, :customer_profile_id => self.billing_profile.customer_profile_id, #billing_profile_id
                            :customer_payment_profile_id => customer_payment_id}}
      )
      logger.info @credit_card.out_options.to_s
      logger.info ({:zipcode => zipcode, :customer_profile_id => self.billing_profile.customer_profile_id, #billing_profile_id
                        :customer_payment_profile_id => customer_payment_id}).to_s
    end


    # def validate_credit_card
    #   unless @credit_card.valid?
    #    @credit_card.errors.full_messages.each do |message|
    #      errors.add_to_base message
    #    end
    #    raise ZepFrog::CustomError, (self.class.to_s + "." + "validate_credit_card" + ":" + errors.full_messages.to_s)
    #   end    
    # end


    # include ActiveMerchant::Billing::CreditCardMethods



end
